package cn.dansj.common.utils.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

class EnumDeserializer<T extends Enum<T>> extends StdDeserializer<T> {
    private final Map<String, T> nameMap = new HashMap<>();
    private final Map<String, T> jsonValueMap = new HashMap<>();
    private final boolean caseSensitive;
    private final Class<T> enumClass;

    public EnumDeserializer(Class<T> enumClass) {
        super(enumClass);
        this.enumClass = enumClass;
        this.caseSensitive = false; // 默认不区分大小写

        // 初始化枚举名称映射
        for (T enumConstant : getEnumConstants()) {
            nameMap.put(enumConstant.name().toLowerCase(), enumConstant);
            // 扫描@JsonValue字段
            scanJsonValueFields(enumConstant);
        }
    }

    private T[] getEnumConstants() {
        return enumClass.getEnumConstants();
    }

    private void scanJsonValueFields(T enumConstant) {
        Arrays.stream(enumConstant.getClass().getDeclaredFields()).filter(f -> f.isAnnotationPresent(com.fasterxml.jackson.annotation.JsonValue.class))
                .forEach(f -> {
                    f.setAccessible(true);
                    try {
                        Object value = f.get(enumConstant);
                        if (value != null) {
                            jsonValueMap.put(value.toString().toLowerCase(), enumConstant);
                        }
                    } catch (IllegalAccessException ex) {
                        // 忽略无法访问的字段
                    }
                });
    }

    @Override
    public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        if (p.currentToken() == JsonToken.VALUE_STRING) {
            String text = p.getText().trim();
            if (text.isEmpty()) {
                return null;
            }

            String lookupKey = caseSensitive ? text : text.toLowerCase();

            // 1. 尝试按枚举名称解析
            T result = nameMap.get(lookupKey);
            if (result != null) {
                return result;
            }

            // 2. 尝试按@JsonValue字段解析
            result = jsonValueMap.get(lookupKey);
            if (result != null) {
                return result;
            }

            // 3. 尝试按枚举toString()解析
            for (T enumConstant : getEnumConstants()) {
                if (enumConstant.toString().equalsIgnoreCase(text)) {
                    return enumConstant;
                }
            }

            // 4. 最后尝试使用原始名称解析（区分大小写）
            try {
                return Enum.valueOf(enumClass, text);
            } catch (IllegalArgumentException e) {
                throw ctxt.weirdStringException(text, handledType(), "无法解析为有效的枚举值");
            }
        }
        throw ctxt.wrongTokenException(p, handledType(), JsonToken.VALUE_STRING, "需要字符串值");
    }
}